package br.com.framework.app.exceptionhandler;

import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;

import br.com.framework.apresentacao.util.FacesMessagesUtil;

/**
 * Handler de Exceções. Permite que qualquer erro inesperado seja redirecionado para uma tela de erros personalizada.
 * Evitando apresentar stacktrace para o usuário.
 * 
 * @author Cleber
 *
 */
public class CustomExceptionHandler extends ExceptionHandlerWrapper {
	
	private static final Logger LOGGER = Logger
			.getLogger(CustomExceptionHandler.class);
	
	private ExceptionHandler wrapped;

	CustomExceptionHandler(ExceptionHandler exception) {
		this.wrapped = exception;
	}

	@Override
	public ExceptionHandler getWrapped() {
		return wrapped;
	}

	@Override
	public void handle() throws FacesException {

		final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents()
				.iterator();
		while (i.hasNext()) {
			ExceptionQueuedEvent event = i.next();
			ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event
					.getSource();

			// get the exception from context
			Throwable t = context.getException();

			final FacesContext fc = FacesContext.getCurrentInstance();
			final NavigationHandler nav = fc.getApplication()
					.getNavigationHandler();

			// here you do what ever you want with exception
			try {
				Throwable rootCause = ExceptionUtils.getRootCause(t);
				// LOGGER error ?
				LOGGER.error("Unexpected Exception!", rootCause);
				// redirect error page
				FacesMessagesUtil.getCurrentInstance().addMessageError(
						null, rootCause.getMessage());
				nav.handleNavigation(fc, null, "/pages/public/errorPage.xhtml?faces-redirect=true");
				fc.renderResponse();

			} finally {
				// remove it from queue
				i.remove();
			}
		}
		// parent hanle
		getWrapped().handle();
	}
}